package cn.lenqq.Utils;

import javax.crypto.Cipher;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.*;
import java.util.Base64;
import java.util.logging.Logger;

public class RSAUtil {

    static Logger log = Logger.getLogger(RSAUtil.class.getName());

    public static final String PRIVATE_KEY_FILE_PATH = System.getProperty("user.dir")+File.separator+"rsa"+File.separator+"PrivateKey.txt";
    public static final String PUBLIC_KEY_FILE_PATH = System.getProperty("user.dir")+File.separator+"rsa"+File.separator+"PublicKey.txt";


    public static void generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        log.info("### 生成公钥：" + publicKey.toString());
        saveKeyToFile(PUBLIC_KEY_FILE_PATH, publicKey);

        PrivateKey privateKey = keyPair.getPrivate();
        log.info("### 生成私钥：" + privateKey.toString());
        saveKeyToFile(PRIVATE_KEY_FILE_PATH, privateKey);
    }

    private static void saveKeyToFile(String filePath, Object key){
        FileOutputStream fileOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        Path path = checkFilePath(filePath);
        try {
            fileOutputStream = new FileOutputStream(path.toFile());

            objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(key);
            log.info("key save to " + filePath);

        } catch (IOException e) {
            log.severe("保存密钥程序发生异常："+e.getMessage());
            throw new RuntimeException(e);
        }finally {
            if(objectOutputStream != null){
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    log.severe("保存密钥程序发生异常："+e.getMessage());
                }
            }
            if(fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    log.severe("保存密钥程序发生异常："+e.getMessage());
                }
            }
        }

    }

    private static Path checkFilePath(String filePath){
        Path path = Paths.get(filePath);

        // 检查父目录是否存在，如果不存在则创建
        Path parentPath = path.getParent();
        if (parentPath != null && !Files.exists(parentPath)) {
            try {
                Files.createDirectories(parentPath);
            } catch (IOException e) {
                throw new RuntimeException("创建密钥文件目录发生异常！"+e.getMessage());
            }
        }

        // 检查文件是否存在，如果不存在则创建
        if (!Files.exists(path)) {
            try {
                Files.write(path, new byte[0], StandardOpenOption.CREATE);
            } catch (IOException e) {
                throw new RuntimeException("创建密钥文件发生异常！"+e.getMessage());
            }
        }

        return path;
    }

    public static String encrypt (String data ){
        byte[] encryptData = null;
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            File file = new File(PUBLIC_KEY_FILE_PATH);
            if(!file.exists()){
                generateKeyPair();
            }
            FileInputStream fileInputStream = new FileInputStream(file);
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            Object o = objectInputStream.readObject();
            cipher.init(Cipher.ENCRYPT_MODE, (PublicKey)o);
            encryptData = cipher.doFinal(data.getBytes());
        } catch (Exception e) {
            log.severe("加密程序发生异常："+ e.getMessage());
        }
        String result = Base64.getEncoder().encodeToString(encryptData);
        log.info("加密结果："+result);
        return result;
    }

    public  static String decrypt (String data ){
        byte[] decryptData = null;
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            File file = new File(PRIVATE_KEY_FILE_PATH);
            if(!file.exists()){
                generateKeyPair();
            }
            FileInputStream fileInputStream = new FileInputStream(file);
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            Object o = objectInputStream.readObject();
            cipher.init(Cipher.DECRYPT_MODE, (PrivateKey)o);
            decryptData = cipher.doFinal(Base64.getDecoder().decode(data));
        } catch (Exception e) {
            log.severe("解密程序发生异常："+ e.getMessage());
        }
        String result = new String (decryptData);
        log.info("解密结果：" + result);
        return result;
    }

    public static void main(String[] args) {
        //        generateKeyPair();

//        log.info(encrypt("123456"));

        String encryptString = "Au7l7msReZzfntK6pqo1mx8BthwNe1OSgudOVNb5jgtCk6QSp4tgmz1xEc1zqum2FIfUt5rwpwncTHaCIevtdcDVWntK1oZHLav+CuFFWpFO7wgerB/Ls+P+6+oYdKtx4bQvn6B7AToF3N5iZGfQr/lMBBZHIDHJWExgzzxWNeWAp4pb3QR5dc5C0+YTHPRSrxTxPAlQG0ob1q8KRJ44QdcDoUp8LqnWaid7f/iVFKa724bHBlEo2x8ppR0DUG7oYJkTSZg44oLkBJP8OI5qYdePGIFjD3TGBMlHgZWfw4pwOjLvCAi++ny012Jo+CDK/xgpovyeGLspePaXKWATnA==";
        log.info(decrypt(encryptString));
    }
}
